/*
Resampling method encapsuated in a class. 
Input: STL vector of type double
Output: STL vector of integer indicating resampling indecies
*/
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <vector>
#include "roundup.h"
#include <math.h>
//#include"JF_print_vector.h"

using namespace std;

class Resampling {
public:
	Resampling(void);
	~Resampling(void);
	vector<int> resample(vector<double> weights) const;
	vector<int> resample_monte_carlo(vector<double> weights) const;
	void resample_naive_test(int length = 3)const;
private:
	int region(double particle,vector<double> weights) const;
protected:

};

Resampling::Resampling(){
}

Resampling::~Resampling(){
}

int Resampling::region(double particle,vector<double> weights) const{
	int index = 0;
	double sum = 0;
	for (int i = 0; i < weights.size(); i++){
		sum += weights[i];
		if (sum>particle){
			index = i;
			break;
		}
	}
	return index;
}

vector<int> Resampling::resample_monte_carlo(vector <double> weights) const{
	
	vector<double> new_sample_number;
	vector<int> new_sample_indeces;
	int index_to_push, rand_buf;
	double particle;

	cout<<" Input-------Resample"<<endl;
	for (int i = 0; i < weights.size(); i++)
	{
		cout<<" "<<weights[i]<<"	";
		//RAMDONLY GENERATE SAMPLE
//		srand(time(NULL));
//		rand_buf = rand();
//		particle = (double)(rand_buf % 10000 + 1.0)/10000.0;	//0-1		//EVEN IF rand() IS UNIFORMAL, THIS MIGHT NOT BE UNIFORM DISTRIBUTED
		particle = (double)(rand() % 10000 + 1.0)/10000.0;	//0-1		//EVEN IF rand() IS UNIFORMAL, THIS MIGHT NOT BE UNIFORM DISTRIBUTED
		//COMPUTE WHICH AREA IT FELL INTO 
		index_to_push = region(particle, weights);		//BE CAREFUL! TEST IT!
		cout<<" "<<index_to_push<<endl;
		//REPORT INDEX
		new_sample_indeces.push_back(index_to_push);
	}
	cout<<endl;
	return new_sample_indeces;
}


vector<int> Resampling::resample(vector <double> weights) const{
	
	vector<double> new_sample_number;
	vector<int> new_sample_indeces;
	double freq;
	//COMPUTE FREQUENCY
	cout<<"Input:"<<endl;
	for (int i = 0; i < weights.size(); i++)
	{
		freq = weights[i]*(double)weights.size();		//NORMALIZE TO TIMES
		new_sample_number.push_back(roundup(freq));
		cout<<" "<<weights[i];
	}
	cout<<endl<<"Number of new sample"<<endl;
	//CHECK OVERALL SIZE
	int new_size = 0;
	for (int i = 0; i < new_sample_number.size(); i ++){
		new_size += new_sample_number[i];
		cout<<" "<<new_sample_number[i];
	}
	cout<<endl;

	//IF NEEDS TO REDUCE SAMPLE FOR APPROXIMATION PURPOSE, WE'D RATHER REMOVE THOSE WITH SMALL WEIGHT VALUE
	return new_sample_indeces;
}

void Resampling::resample_naive_test(int length)const {
//	int length = 3;
	vector<double> test_vector;

	for (int i = 0; i < length; i++)
	{
		test_vector.push_back(rand());
	}

	int sum = 0;
	for (int i = 0; i < test_vector.size(); i++)
	{
		sum += test_vector[i];
	}

	for (int i = 0; i < test_vector.size(); i++)
	{
		test_vector[i] = test_vector[i]/sum;
	}

	sum = 0;
	resample_monte_carlo(test_vector);
	
	cin.get();

}